/********************************************************************************
 * Project Name		[JavaSE_Fundamentals]
 * File Name     	[TestObjectStream.java]
 * Creation Date 	[2015-01-01]
 * 
 * Copyright© ge.y.yang@gmail.com All Rights Reserved
 * 
 * Work hard, play harder, think big and keep fit
 ********************************************************************************/
package io.api;

import java.io.EOFException;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
 * java.io.ObjectInputStream测试<br/>
 * java.io.ObjectOutputStream测试<br/>
 * 
 * 这两个类用于对象的序列化和反序列化
 * 
 * 主要用于对象信息的读取与写入, 对象信息一旦写到文件上那么对象的信息就可以做到持久化了<br/>
 * 
 * 对象输入输出流要注意的细节<br/>
 * 1. 写出到文件的对象所属的类必须要实现Serializable接口<br/>
 * 2. 对象的反序列化创建对象的时候并不会调用构造方法<br/>
 * 3. serialVersionUID<br/>
 * --用于记录class文件的版本信息, 其是通过工程名/包名/类名/成员算出的一个数字 <br/>
 * --反序列化时会读取文件中的serialVersionUID和本地class文件的serialVersionUID进行对比, UID不一致则反序列化失败
 * --如果序列化与反序列化时可能会修改类的成员, 那么最好一开始就给这个类指定一个serialVersionUID<br/>
 * --如果一个类已经指定的serialVersionUID, 在序列化与反序列化时, JVM都不会再计算这个class的serialVersionUID了
 * 4. 如果一个对象的某个数据不想被序列化到硬盘上, 可以使用关键字transient修饰<br/>
 * 5. 如果一个类维护了另外一个类的引用, 那么另外一个类也需要实现Serializable接口<br/>
 * 
 * @author 不落的太阳(Sean Yang aka ShortPeace)
 * @version 1.0
 * @since jdk 1.8
 * 
 */
public class TestObjectStream {

	/**
	 * 对象序列化
	 */
	public static void writeObject() {
		ObjectOutputStream out = null;

		try {
			out = new ObjectOutputStream(new FileOutputStream("object.data"));

			out.writeObject(new Student("Sean Yang", "SUFE", 30));
			out.writeObject(new Student("Sean Yang", "TYWZ", 18));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (out != null) {
					out.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 对象反序列化
	 */
	public static void readObject() {
		ObjectInputStream in = null;

		try {
			in = new ObjectInputStream(new FileInputStream("object.data"));

			Student student = null;
			try {
				while (in.available() != -1) {
					student = (Student) in.readObject();
					System.out.println(student);
				}
			} catch (EOFException e) {
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} finally {
			try {
				if (in != null) {
					in.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public static void main(String[] args) {
		writeObject();
		readObject();
	}
}

/**
 * 
 * @author 不落的太阳(Sean Yang aka ShortPeace)
 * @version 1.0
 * @since jdk 1.8
 *
 */
class Student implements Serializable {

	private static final long serialVersionUID = 5306399104161924777L;

	private final String name;
	private final String schoolName;
	private final Integer age;

	public Student(String name, String schoolName, Integer age) {
		super();
		this.name = name;
		this.schoolName = schoolName;
		this.age = age;
	}

	@Override
	public String toString() {
		return "Student [name=" + name + ", schoolName=" + schoolName + ", age=" + age + "]";
	}
}
